import base64
import datetime
import io
import os
import pathlib
import tempfile
import uuid

import cv2
from celery import Celery
from flask import abort, current_app, request

from controllers.base_controller import BaseController
from utils.api_response_utils import create_error_response, create_success_response
from video_processing_modules.video_processor import VideoProcessor

# 初始化 Celery，在 URL 中添加 Redis 密码
celery = Celery(__name__, broker="redis://:password@localhost:6379/10")


class VideoProcessingController(BaseController):
    """视频处理控制器，处理视频处理相关请求"""

    def __init__(self, import_name):
        """
        初始化控制器

        Args:
            import_name: 导入名称
        """
        # 初始化为None，稍后在路由处理函数中获取
        self.minio_client = None
        self.video_processor = VideoProcessor()
        super().__init__("视频处理", import_name, url_prefix="")

    def register_routes(self):
        """注册路由"""

        def _handle_video_extraction(is_async):
            """处理视频文本提取的通用逻辑"""
            try:
                data = request.get_json()
                video_base64 = data.get("video_base64")

                if not video_base64:
                    return create_error_response(
                        400,
                        "参数video_base64的值为空，请提供有效的base64编码的视频数据",
                    )

                if is_async:
                    # 异步处理
                    extract_frames = data.get("extract_frames", False)
                    frame_interval = data.get("frame_interval", 5.0)
                    max_frames = data.get("max_frames", 10)
                    task = process_video.apply_async(
                        args=[video_base64, extract_frames, frame_interval, max_frames],
                        queue="video_processing",
                    )
                    return create_success_response("任务已启动", {"task_id": task.id})
                else:
                    # 同步处理
                    language = data.get("language", "zh-CN")
                    is_segment = data.get("is_segment", False)

                    video_data = base64.b64decode(video_base64)
                    temp_dir = tempfile.gettempdir()
                    unique_id = uuid.uuid4()
                    temp_video_path = os.path.join(
                        temp_dir, f"temp_video_{unique_id}.mp4"
                    )
                    with open(temp_video_path, "wb") as f:
                        f.write(video_data)

                    cap = cv2.VideoCapture(temp_video_path)
                    if not cap.isOpened():
                        os.remove(temp_video_path)
                        return create_error_response(
                            400, "无法打开视频文件，请检查视频格式是否正确"
                        )
                    cap.release()

                    result = self.video_processor.extract_text_from_video(
                        temp_video_path, is_segment=is_segment, language=language
                    )

                    if os.path.exists(temp_video_path):
                        os.remove(temp_video_path)

                    return create_success_response("处理完成", result)

            except Exception as e:
                self.logger.error(f"处理请求时出错: {str(e)}")
                return create_error_response(500, f"服务器内部错误: {str(e)}")

        @self.route("/extract_video_text_async", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/video_processing/video_extract_text_async.yml")
        def api_extract_video_text_async():
            """异步从视频中提取文字"""
            return _handle_video_extraction(is_async=True)

        @self.route("/extract_video_text", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/video_processing/extract_video_text.yml")
        def api_extract_video_text_sync():
            """同步从视频中提取文字"""
            return _handle_video_extraction(is_async=False)

        @self.route("/task_status/<task_id>", methods=["GET"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/video_processing/video_task_status.yml")
        def task_status(task_id):
            """
            查询指定任务的状态信息

            Args:
                task_id (str): 任务ID

            Returns:
                dict: 包含任务状态信息的字典

            Returns:
                dict: 包含任务状态信息的成功响应

            """
            task = celery.AsyncResult(task_id)
            if task.state == "PENDING":
                response = {
                    "state": task.state,
                    "current": 0,
                    "total": 1,
                    "status": "Pending...",
                }
            elif task.state != "FAILURE":
                response = {
                    "state": task.state,
                    "current": task.info.get("current", 0),
                    "total": task.info.get("total", 1),
                    "status": task.info.get("status", ""),
                }
                if "result" in task.info:
                    response["result"] = task.info["result"]
            else:
                # 任务失败
                response = {
                    "state": task.state,
                    "current": 1,
                    "total": 1,
                    "status": str(task.info),  # 错误信息
                }
            return create_success_response("任务状态", response)

        @self.route("/extract_video_frames", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/video_processing/extract_video_frames.yml")
        def api_extract_video_frames():
            """从视频中提取帧并保存到指定目录"""
            # 手动抛出 503 服务不可用异常
            abort(
                503,
                description="该接口暂时不可用，请使用/extract_face_frames_from_video_to_minio提取视频帧",
            )
            try:
                data = request.parsed_data
                video_base64 = data.get("video_base64")
                filename = data.get("filename")
                frame_interval = data.get("frame_interval", 10)  # 默认每隔10帧提取一张
                max_frames = data.get("max_frames", 50)  # 默认最多提取50帧

                # 参数验证
                if not video_base64:
                    return create_error_response(
                        400,
                        "参数video_base64的值为空，请提供有效的base64编码的视频数据",
                    )
                if not filename:
                    return create_error_response(
                        400, "参数filename的值为空，请提供有效的文件名"
                    )

                # 解码视频数据
                video_data = base64.b64decode(video_base64)
                temp_dir = tempfile.gettempdir()
                unique_id = uuid.uuid4()
                temp_video_path = os.path.join(temp_dir, f"temp_video_{unique_id}.mp4")
                with open(temp_video_path, "wb") as f:
                    f.write(video_data)

                # 检查视频是否可以打开
                cap = cv2.VideoCapture(temp_video_path)
                if not cap.isOpened():
                    os.remove(temp_video_path)
                    return create_error_response(
                        400, "无法打开视频文件，请检查视频格式是否正确"
                    )

                # 获取视频信息
                total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))

                # 创建保存目录
                today = datetime.datetime.now().strftime("%Y-%m-%d")
                save_dir = os.path.join("..", "bhrm-video-frames", today, filename)
                pathlib.Path(save_dir).mkdir(parents=True, exist_ok=True)

                # 提取帧
                frame_paths = []
                frame_count = 0
                frame_index = 0

                while frame_count < max_frames and frame_index < total_frames:
                    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
                    ret, frame = cap.read()
                    if not ret:
                        break

                    # 保存帧
                    frame_filename = f"{filename}_{frame_count:04d}.jpg"
                    frame_path = os.path.join(save_dir, frame_filename)
                    cv2.imwrite(frame_path, frame)

                    # 添加到结果列表
                    relative_path = os.path.join(
                        "bhrm-video-frames", today, filename, frame_filename
                    )
                    frame_paths.append(relative_path.replace("\\", "/"))

                    frame_count += 1
                    frame_index += frame_interval

                cap.release()

                # 删除临时文件
                if os.path.exists(temp_video_path):
                    os.remove(temp_video_path)

                # 返回结果
                result = {
                    "total_frames_extracted": frame_count,
                    "frame_paths": frame_paths,
                    "video_info": {
                        "total_frames": total_frames,
                        "frame_interval": frame_interval,
                        "max_frames": max_frames,
                    },
                }

                return create_success_response(f"成功提取{frame_count}帧图像", result)
            except Exception as e:
                self.logger.error(f"处理请求时出错: {str(e)}")
                return create_error_response(500, f"服务器内部错误: {str(e)}")

        @self.route("/extract_video_frames_to_minio", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/video_processing/extract_video_frames_to_minio.yml")
        def api_extract_video_frames_to_minio():
            """从视频中提取帧并存储到MinIO"""

            abort(
                503,
                description="该接口暂时不可用，请使用/extract_face_frames_from_video_to_minio提取视频帧",
            )
            try:
                self.logger.info("收到提取视频帧并上传到MinIO的请求")

                # 获取或初始化MinIO客户端
                if hasattr(current_app, "minio_client"):
                    minio_client = current_app.minio_client
                    self.logger.info("使用全局MinIO客户端")
                else:
                    abort(503, "Minio对象构建失败")

                # 检查MinIO客户端是否可用
                if not minio_client.is_available():
                    self.logger.error("MinIO存储服务不可用，请检查配置")
                    return create_error_response(500, "MinIO存储服务不可用，请检查配置")

                self.logger.info(
                    f"MinIO客户端可用，存储桶: {minio_client.config.bucket}"
                )

                data = request.parsed_data
                video_base64 = data.get("video_base64")
                filename_prefix = data.get(
                    "filename_prefix", f"video_{uuid.uuid4().hex[:8]}"
                )
                frame_interval = data.get("frame_interval", 10)  # 默认每隔10帧提取一张
                max_frames = data.get("max_frames", 50)  # 默认最多提取50帧

                self.logger.info(
                    f"请求参数: filename_prefix={filename_prefix}, frame_interval={frame_interval}, max_frames={max_frames}"
                )

                # 参数验证
                if not video_base64:
                    self.logger.warning("参数video_base64的值为空")
                    return create_error_response(
                        400,
                        "参数video_base64的值为空，请提供有效的base64编码的视频数据",
                    )

                self.logger.info("开始解码视频数据")
                # 解码视频数据
                video_data = base64.b64decode(video_base64)
                video_size = len(video_data) / (1024 * 1024)  # 转换为MB
                self.logger.info(f"视频数据大小: {video_size:.2f} MB")

                temp_dir = tempfile.gettempdir()
                unique_id = uuid.uuid4()
                temp_video_path = os.path.join(temp_dir, f"temp_video_{unique_id}.mp4")
                with open(temp_video_path, "wb") as f:
                    f.write(video_data)
                self.logger.info(f"视频数据已保存到临时文件: {temp_video_path}")

                # 检查视频是否可以打开
                self.logger.info("检查视频文件是否可以打开")
                cap = cv2.VideoCapture(temp_video_path)
                if not cap.isOpened():
                    os.remove(temp_video_path)
                    self.logger.error("无法打开视频文件，可能格式不正确")
                    return create_error_response(
                        400, "无法打开视频文件，请检查视频格式是否正确"
                    )

                # 获取视频信息
                fps = cap.get(cv2.CAP_PROP_FPS)
                total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
                width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
                height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
                duration = total_frames / fps if fps > 0 else 0

                self.logger.info(
                    f"视频信息: {width}x{height}, {fps} FPS, {total_frames} 帧, {duration:.2f} 秒"
                )

                # 提取帧
                self.logger.info(
                    f"开始提取视频帧，间隔: {frame_interval} 帧，最大帧数: {max_frames}"
                )
                frame_urls = []
                frame_count = 0
                frame_index = 0

                today = datetime.datetime.now().strftime("%Y-%m-%d")
                folder_path = f"{today}/{filename_prefix}"
                self.logger.info(f"存储路径: {folder_path}")

                start_time = datetime.datetime.now()

                while frame_count < max_frames and frame_index < total_frames:
                    cap.set(cv2.CAP_PROP_POS_FRAMES, frame_index)
                    ret, frame = cap.read()
                    if not ret:
                        self.logger.warning(f"无法读取帧 {frame_index}")
                        break

                    # 生成帧文件名
                    frame_filename = f"{filename_prefix}_{frame_count:04d}.jpg"
                    object_name = f"{folder_path}/{frame_filename}"

                    # 将帧编码为JPEG格式
                    _, buffer = cv2.imencode(".jpg", frame)
                    frame_bytes = io.BytesIO(buffer)
                    frame_size = len(buffer)  # / 1024  # 转换为KB

                    # 上传到MinIO
                    self.logger.debug(
                        f"上传帧 {frame_count} (索引: {frame_index}) 到 MinIO, 大小: {(frame_size / 1024):.2f} KB"
                    )
                    frame_url = minio_client.upload_bytes(
                        frame_bytes, object_name, content_type="image/jpeg"
                    )

                    if frame_url:
                        frame_urls.append(
                            {
                                "frame_id": frame_count,
                                "frame_index": frame_index,
                                "timestamp": frame_index / fps if fps > 0 else 0,
                                "url": frame_url,
                                "frame_filename": frame_filename,
                                "frame_size": frame_size,
                            }
                        )

                        frame_count += 1
                        if frame_count % 10 == 0:
                            self.logger.info(f"已处理 {frame_count} 帧")
                    else:
                        self.logger.error(f"上传帧到MinIO失败: {object_name}")

                    frame_index += frame_interval

                cap.release()

                end_time = datetime.datetime.now()
                process_time = (end_time - start_time).total_seconds()
                self.logger.info(
                    f"帧提取完成，共提取 {frame_count} 帧，处理时间: {process_time:.2f} 秒"
                )

                # 删除临时文件
                if os.path.exists(temp_video_path):
                    os.remove(temp_video_path)
                    self.logger.info("临时视频文件已删除")

                # 返回结果
                result = {
                    "total_frames_extracted": frame_count,
                    "frame_urls": frame_urls,
                    "video_info": {
                        "fps": fps,
                        "total_frames": total_frames,
                        "width": width,
                        "height": height,
                        "duration_seconds": duration,
                        "frame_interval": frame_interval,
                        "max_frames": max_frames,
                    },
                    "storage_info": {
                        "provider": "minio",
                        "bucket": minio_client.config.bucket,
                        "base_folder": folder_path,
                    },
                    "process_time_seconds": process_time,
                }

                self.logger.info(f"请求处理完成，返回 {frame_count} 帧的URL")
                return create_success_response(
                    f"成功提取并上传{frame_count}帧图像到MinIO", result
                )
            except Exception as e:
                self.logger.error(f"处理请求时出错: {str(e)}")
                import traceback

                self.logger.error(traceback.format_exc())
                return create_error_response(500, f"服务器内部错误: {str(e)}")

        @self.route("/extract_face_frames_from_video", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/video_processing/extract_face_frames.yml")
        def api_extract_face_frames_from_video():
            """从视频中提取包含人脸的关键帧并保存到本地"""
            # 手动抛出 503 服务不可用异常
            abort(
                503,
                description="该接口暂时不可用，请使用/extract_face_frames_from_video_to_minio提取视频帧",
            )
            try:
                self.logger.info("收到提取视频人脸关键帧请求")

                data = request.parsed_data
                video_base64 = data.get("video_base64")
                filename = data.get("filename")
                min_face_size = data.get("min_face_size", 50)  # 最小人脸尺寸
                similarity_threshold = data.get(
                    "similarity_threshold", 0.8
                )  # 人脸相似度阈值
                max_frames = data.get("max_frames", 20)  # 最大提取帧数

                # 参数验证
                if not video_base64:
                    return create_error_response(
                        400,
                        "参数video_base64的值为空，请提供有效的base64编码的视频数据",
                    )
                if not filename:
                    return create_error_response(
                        400, "参数filename的值为空，请提供有效的文件名"
                    )

                # 解码视频数据
                video_data = base64.b64decode(video_base64)
                temp_dir = tempfile.gettempdir()
                unique_id = uuid.uuid4()
                temp_video_path = os.path.join(temp_dir, f"temp_video_{unique_id}.mp4")
                with open(temp_video_path, "wb") as f:
                    f.write(video_data)

                # 创建保存目录
                today = datetime.datetime.now().strftime("%Y-%m-%d")
                save_dir = os.path.join("..", "bhrm-video-frames", today, filename)
                pathlib.Path(save_dir).mkdir(parents=True, exist_ok=True)

                try:
                    result = self.video_processor.extract_face_frames(
                        temp_video_path,
                        min_face_size=min_face_size,
                        similarity_threshold=similarity_threshold,
                        max_frames=max_frames,
                    )

                    # 保存关键帧到本地
                    frame_paths = []
                    for frame_info in result["key_frames"]:
                        frame_filename = (
                            f"{filename}_face_{frame_info['frame_id']:04d}.jpg"
                        )
                        frame_path = os.path.join(save_dir, frame_filename)
                        cv2.imwrite(frame_path, frame_info["frame"])

                        # 添加路径信息
                        relative_path = os.path.join(
                            "bhrm-video-frames", today, filename, frame_filename
                        )
                        frame_paths.append(relative_path.replace("\\", "/"))

                        # 更新帧信息，移除帧数据，添加路径
                        frame_info.pop("frame")
                        frame_info["path"] = relative_path.replace("\\", "/")

                    # 更新结果
                    result["frame_paths"] = frame_paths

                    # 删除临时视频文件
                    if os.path.exists(temp_video_path):
                        os.remove(temp_video_path)

                    return create_success_response(
                        f"成功提取{len(frame_paths)}个人脸关键帧", result
                    )

                except Exception as e:
                    if os.path.exists(temp_video_path):
                        os.remove(temp_video_path)
                    raise e

            except Exception as e:
                self.logger.error(f"处理请求时出错: {str(e)}")
                import traceback

                self.logger.error(traceback.format_exc())
                return create_error_response(500, f"服务器内部错误: {str(e)}")

        @self.route("/extract_face_frames_from_video_to_minio", methods=["POST"])
        @self.validate_json_request()
        @self.swagger_from("swagger_docs/video_processing/extract_face_frames_to_minio.yml")
        def api_extract_face_frames_from_video_to_minio():
            """从视频中提取包含人脸的关键帧并存储到MinIO"""
            try:
                self.logger.info("收到提取视频人脸关键帧并上传到MinIO的请求")

                # 获取或初始化MinIO客户端
                if hasattr(current_app, "minio_client"):
                    # minio_client: Any = current_app.config["MINIO_CLIENT"]
                    minio_client = current_app.minio_client
                    self.logger.info("使用全局MinIO客户端")
                else:
                    # minio_client = MinioClient()
                    # self.logger.warning("使用本地MinIO客户端，而非全局客户端")
                    # 如果minio对象不存在直接抛出异常返回
                    abort(503, "Minio对象构建失败")

                # 检查MinIO客户端是否可用
                if not minio_client.is_available():
                    self.logger.error("MinIO存储服务不可用，请检查配置")
                    return create_error_response(500, "MinIO存储服务不可用，请检查配置")

                self.logger.info(
                    f"MinIO客户端可用，存储桶: {minio_client.config.bucket}"
                )

                data = request.get_json()
                video_base64 = data.get("video_base64")
                filename_prefix = data.get(
                    "filename_prefix", f"video_{uuid.uuid4().hex[:8]}"
                )
                min_face_size = data.get("min_face_size", 50)  # 最小人脸尺寸
                similarity_threshold = data.get(
                    "similarity_threshold", 0.7
                )  # 人脸相似度阈值
                max_frames = data.get("max_frames", 20)  # 最大提取帧数
                det_thresh = data.get("det_thresh", 0.5)  # 人脸检测置信度

                self.logger.info(
                    f"请求参数: filename_prefix={filename_prefix}, min_face_size={min_face_size}, similarity_threshold={similarity_threshold}, max_frames={max_frames}"
                )

                # 参数验证
                if not video_base64:
                    self.logger.warning("参数video_base64的值为空")
                    return create_error_response(
                        400,
                        "参数video_base64的值为空，请提供有效的base64编码的视频数据",
                    )

                # 解码视频数据
                video_data = base64.b64decode(video_base64)
                video_size = len(video_data) / (1024 * 1024)  # 转换为MB
                self.logger.info(f"视频数据大小: {video_size:.2f} MB")

                temp_dir = tempfile.gettempdir()
                unique_id = uuid.uuid4()
                temp_video_path = os.path.join(temp_dir, f"temp_video_{unique_id}.mp4")
                with open(temp_video_path, "wb") as f:
                    f.write(video_data)
                self.logger.info(f"视频数据已保存到临时文件: {temp_video_path}")

                try:
                    start_time = datetime.datetime.now()

                    # 提取关键帧
                    result = self.video_processor.extract_face_frames(
                        video_path=temp_video_path,  # 视频路径
                        min_face_size=min_face_size,  # 最小人脸尺寸
                        similarity_threshold=similarity_threshold,  # 人脸相似度阈值
                        max_frames=max_frames,  # 最大提取帧数
                        det_thresh=det_thresh,  # 人脸检测置信度
                    )

                    # 上传关键帧到MinIO
                    today = datetime.datetime.now().strftime("%Y-%m-%d")
                    folder_path = f"{today}/{filename_prefix}"

                    frame_urls = []
                    for frame_info in result["key_frames"]:
                        # 生成帧文件名
                        frame_filename = f"{filename_prefix}_face_{int(frame_info['frame_id']):04d}.jpg"
                        object_name = f"{folder_path}/{frame_filename}"

                        # 将帧编码为JPEG格式
                        _, buffer = cv2.imencode(".jpg", frame_info["frame"])
                        frame_bytes = io.BytesIO(buffer.tobytes())
                        frame_size = len(buffer.tobytes())  # 获取字节数据大小

                        # 上传到MinIO
                        self.logger.debug(
                            f"上传帧 {frame_info['frame_id']} (索引: {frame_info['frame_index']}) 到 MinIO, 大小: {(frame_size / 1024):.2f} KB"
                        )
                        frame_url = minio_client.upload_bytes(
                            frame_bytes, object_name, content_type="image/jpeg"
                        )

                        if frame_url:
                            # 创建帧URL信息
                            frame_url_info = {
                                "frame_id": frame_info["frame_id"],
                                "frame_index": frame_info["frame_index"],
                                "timestamp": frame_info["timestamp"],
                                "url": frame_url,
                                "frame_filename": frame_filename,
                                "face_count": frame_info["face_count"],
                                "frame_size": frame_size,
                            }
                            frame_urls.append(frame_url_info)

                    # 删除临时视频文件
                    if os.path.exists(temp_video_path):
                        os.remove(temp_video_path)

                    # 计算总处理时间
                    total_process_time = (
                        datetime.datetime.now() - start_time
                    ).total_seconds()

                    # 构建响应结果
                    response_result = {
                        "total_frames_processed": result["total_frames_processed"],
                        "key_frames_extracted": len(frame_urls),
                        "frame_urls": frame_urls,
                        "video_info": result["video_info"],
                        "storage_info": {
                            "provider": "minio",
                            "bucket": minio_client.config.bucket,
                            "base_folder": folder_path,
                        },
                        "process_time_seconds": total_process_time,
                    }

                    return create_success_response(
                        f"成功提取并上传{len(frame_urls)}帧人脸图像到MinIO",
                        response_result,
                    )

                except Exception as e:
                    if os.path.exists(temp_video_path):
                        os.remove(temp_video_path)
                    raise e

            except Exception as e:
                self.logger.error(f"处理请求时出错: {str(e)}")
                import traceback

                self.logger.error(traceback.format_exc())
                return create_error_response(500, f"服务器内部错误: {str(e)}")


@celery.task(bind=True)
def process_video(self, video_base64, extract_frames, frame_interval, max_frames):
    """
    处理视频文件并提取文本。

    Args:
        video_base64 (str): 视频文件的Base64编码字符串。
        extract_frames (bool): 是否从视频中提取帧。
        frame_interval (int): 提取帧的时间间隔（以秒为单位）。
        max_frames (int): 从视频中提取的最大帧数。

    Returns:
        dict: 处理结果，包含从视频中提取的文本和其他相关信息。

    Raises:
        Exception: 如果处理过程中出现错误，将抛出异常。
    """
    try:
        # 模拟处理步骤
        total_steps = 5
        self.update_state(
            state="PROGRESS",
            meta={"current": 1, "total": total_steps, "status": "解码视频数据"},
        )
        video_data = base64.b64decode(video_base64)

        self.update_state(
            state="PROGRESS",
            meta={"current": 2, "total": total_steps, "status": "保存临时文件"},
        )
        temp_dir = tempfile.gettempdir()
        unique_id = uuid.uuid4()
        temp_video_path = os.path.join(temp_dir, f"temp_video_{unique_id}.mp4")
        with open(temp_video_path, "wb") as f:
            f.write(video_data)

        self.update_state(
            state="PROGRESS",
            meta={"current": 3, "total": total_steps, "status": "检查视频文件"},
        )
        cap = cv2.VideoCapture(temp_video_path)
        if not cap.isOpened():
            raise Exception("无法打开视频文件，请检查视频格式是否正确")
        fps = cap.get(cv2.CAP_PROP_FPS)
        total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
        width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
        duration = total_frames / fps if fps > 0 else 0
        cap.release()

        self.update_state(
            state="PROGRESS",
            meta={
                "current": 4,
                "total": total_steps,
                "status": "处理视频",
                "duration": duration,
                "width": width,
                "height": height,
                "fps": fps,
                "total_frames": total_frames,
            },
        )

        result = self.video_processor.extract_text_from_video(
            temp_video_path,
            extract_frames=extract_frames,
            frame_interval=frame_interval,
            max_frames=max_frames,
        )

        self.update_state(
            state="PROGRESS",
            meta={"current": 5, "total": total_steps, "status": "完成处理"},
        )
        if os.path.exists(temp_video_path):
            os.remove(temp_video_path)

        return result
    except Exception as e:
        raise Exception(str(e))
